What is Borrowing, Reference (&)

In reference & Borrowing ownership of the value is not taken.
References are always created using &
Rust track lifetimes of all references to ensure they live long enough
Wrt to C++:
  Safer avoids Crashes/Dangling References.
  no new copies are created, achieved by passing the reference of a variable.

Reference vs Borrowing

Reference (immutable) Borrowing (Mutable Reference)
Definition A reference is just a pointer storing address of variable.
References are immutable.

fn main() {
    let a = 10;
    let b = &a;
    //b = 2;        Error
    println!("b={}",b);
}
$ cargo run
10
                        
Borrowed value can be changed.

fn main() {
    let mut a = 10;
    let b = &mut a;
    *b = 11;
    println!("b={}",b);
}
                        

Types of Borrowing

Dangling References (Allowed in C++, but not in Rust)

Dangling pointer? Pointer points to memory, memory is freed and pointer is used.
Dangling reference? Similar to Dangling pointer, when reference to a value is used, value is freed and reference is used after that.

C++ (Crash in C++) Rust
Dangling References Dangling References Allowed in C++

//Function returning reference
int& fun() {
    int b = 10;
    return b;
}

int main() {
    //a is reference variable pointing to b,
    which does not exist    
    int &a = fun();
    cout << a;            
}
# g++ test.cpp   //No compile error
# ./a.out
    Segmentation Fault
                    
Dangling References Not Allowed in Rust

fn fun() -> &i32 {
    let b = 10;
    &b     //Reference returned
}
fn main() {
    let a = fun();
}
$ cargo build
| fn fun() -> &i32
|             ^ expected named lifetime parameter
                    

Exclusive/Mutable References (&mut T)

- References are mutable by Default in C++ (This can cause issues)
- (By default)References are IMMUTABLE in Rust, we need to make them mutable explicitly.
C++ Rust
Mutable? References are mutable by Default in C++

#include <iostream>
int main() {
    int a = 10;
    int &b = a;  // Reference mutable by default
    b = 2;       // Reference changed
    std::cout << a;
}
$ g++ main.cpp
2
                    
References are IMMUTABLE by Default in Rust
References are IMMUTABLE by default

fn main() {
    let mut a = 'A';
    let b:&char = &a;
    *b = 'B';
    println!("{}", *b);
}
$ cargo run
Error
                                    
References are made MUTABLE explicitly

fn main() {
    let mut a = 'A';
    let b:&mut char = &mut a;
    *b = 'B';
    println!("{}", *b);
}
$ cargo run
B
                                    

Two Mutable references not allowed in same scope

Why Rust avoids 2 mutable ref in same scope?
  To prevent data race b/w 2 threads. 1 mutable ref change and other also change.
C++ Crash

int main()
{
    char* s1 = new char[1];
    char* s2 = s1;
    *s1 = 'a';
    delete s1;
    cout << "val=" << (*s2);
}
$ g++ test.cpp
Crash or Undefined behaviour
                    
Rust(No Crash, But compiletime error)
Why not allowed in Rust?
This can be a race condition, where if both mutable references change the data, there is no mechanism synchronize access to the data

fn main() {
    let mut s = String::from("hello");
    let r1 = &mut s;
    let r2 = &mut s;
    println!("{}, {}", r1, r2);
}
$ cargo build
error[E0499]: cannot borrow `s` as mutable more than once at a time
                                    

1 Immutable, 1 Mutable reference not allowed in same scope

This happens because immutable reference is used after mutable

fn main() {
    let mut a = 10;
    let c = &a;
    let b = &mut a;     //Error cannot borrow `a` as mutable because it is also borrowed as immutable
    println!("b={} {c}",b);
}